import React, { useState, useEffect, useRef } from "react";
import Chart from "chart.js/auto";
import "./styles.css";

const App = () => {
  const chartContainer = useRef(null);
  const userChartContainer = useRef(null);

  const [isGeneratingData, setIsGeneratingData] = useState(false);
  const [dataInterval, setDataInterval] = useState(null);
  const [selectedUser, setSelectedUser] = useState(1);
  const [userCount, setUserCount] = useState(10);
  const [userValues, setUserValues] = useState({});
  const [perturbedUserValues, setPerturbedUserValues] = useState({});
  const [chartData, setChartData] = useState({
    labels: [],
    datasets: [
      {
        label: "Input Data Average",
        data: [],
        borderColor: "rgba(75,192,192,1)",
        backgroundColor: "lightgrey",
        fill: false,
      },
      {
        label: "Perturbed Data Average",
        data: [],
        borderColor: "rgba(192,75,192,1)",
        backgroundColor: "lightgrey",
        fill: false,
      },
      {
        label: "Max Value (Original)",
        data: [],
        borderColor: "rgba(255,0,0,1)",
        backgroundColor: "lightcoral",
        fill: false,
      },
      {
        label: "Min Value (Original)",
        data: [],
        borderColor: "rgba(0,0,255,1)",
        backgroundColor: "lightblue",
        fill: false,
      },
      {
        label: "Max Value (Perturbed)",
        data: [],
        borderColor: "rgba(255,0,0,1)",
        backgroundColor: "lightcoral",
        fill: false,
      },
      {
        label: "Min Value (Perturbed)",
        data: [],
        borderColor: "rgba(0,0,255,1)",
        backgroundColor: "lightblue",
        fill: false,
      },
    ],
  });

  const chartRef = useRef(null);
  const userChartRef = useRef(null);

  useEffect(() => {
    // 初始化用户数据
    const initialUserValues = {};
    const initialPerturbedUserValues = {};

    for (let i = 1; i <= userCount; i++) {
      initialUserValues[i] = [];
      initialPerturbedUserValues[i] = [];
    }

    setUserValues(initialUserValues);
    setPerturbedUserValues(initialPerturbedUserValues);
  }, [userCount]);

  const startDataGeneration = () => {
    if (isGeneratingData) return;

    setIsGeneratingData(true);

    // 使用 setInterval 持续产生数据
    setDataInterval(setInterval(generateData, 1000));
  };

  const stopDataGeneration = () => {
    setIsGeneratingData(false);

    // 清除定时器
    clearInterval(dataInterval);
  };

  const generateData = () => {
    // 从输入框获取用户输入的参数
    const lowerBound = parseFloat(document.getElementById("lowerBound").value);
    const upperBound = parseFloat(document.getElementById("upperBound").value);
    const ldpParam = parseFloat(document.getElementById("ldpParam").value);

    // 生成原始数据和扰动数据
    const dataVector = Array.from({ length: userCount }, () =>
      parseFloat(
        (
          Math.random() * (upperBound - lowerBound) +
          parseFloat(lowerBound)
        ).toFixed(2)
      )
    );

    const perturbedDataVector = dataVector.map((value) =>
      parseFloat((value + Math.random() * ldpParam).toFixed(2))
    );

    // 获取当前时间
    const currentTime = new Date().toLocaleTimeString();

    // 计算均值、最大值和最小值
    const dataAvg = dataVector.reduce((acc, val) => acc + val, 0) / userCount;
    const perturbedDataAvg =
      perturbedDataVector.reduce((acc, val) => acc + val, 0) / userCount;
    const MAX1 = Math.max(...dataVector);
    const MIN1 = Math.min(...dataVector);

    // 计算扰动后向量的最大值和最小值
    const MAX2 = Math.max(...perturbedDataVector);
    const MIN2 = Math.min(...perturbedDataVector);

    // 更新所有用户的浮点数值和扰动后的浮点数值
    const updatedUserValues = { ...userValues };
    const updatedPerturbedUserValues = { ...perturbedUserValues };

    for (let i = 1; i <= userCount; i++) {
      const selectedUserData = updatedUserValues[i] || [];
      const perturbedSelectedUserData = updatedPerturbedUserValues[i] || [];

      selectedUserData.push(dataVector[i - 1]);
      perturbedSelectedUserData.push(perturbedDataVector[i - 1]);

      updatedUserValues[i] = selectedUserData;
      updatedPerturbedUserValues[i] = perturbedSelectedUserData;
    }

    // 更新用户数据对象
    setUserValues(updatedUserValues);
    setPerturbedUserValues(updatedPerturbedUserValues);

    // 更新图表数据
    setChartData((prevChartData) => {
      const newChartData = {
        labels: [...prevChartData.labels, currentTime],
        datasets: [
          {
            ...prevChartData.datasets[0],
            data: [...prevChartData.datasets[0].data, dataAvg],
          },
          {
            ...prevChartData.datasets[1],
            data: [...prevChartData.datasets[1].data, perturbedDataAvg],
          },
          {
            ...prevChartData.datasets[2],
            data: [...prevChartData.datasets[2].data, MAX1],
          },
          {
            ...prevChartData.datasets[3],
            data: [...prevChartData.datasets[3].data, MIN1],
          },
          {
            ...prevChartData.datasets[4],
            data: [...prevChartData.datasets[4].data, MAX2],
          },
          {
            ...prevChartData.datasets[5],
            data: [...prevChartData.datasets[5].data, MIN2],
          },
        ],
      };

      // 创建新的Chart实例
      if (chartRef.current) {
        chartRef.current.destroy();
      }

      const ctx = chartContainer.current?.getContext("2d");

      if (ctx) {
        chartRef.current = new Chart(ctx, {
          type: "line",
          data: newChartData,
          options: {
            scales: {
              y: {
                beginAtZero: true,
              },
            },
          },
        });
      }

      return newChartData;
    });
  };

  useEffect(() => {
    if (chartRef.current) {
      chartRef.current.destroy();
    }

    const ctx = chartContainer.current?.getContext("2d");

    if (!chartContainer.current || !ctx) return;

    // 创建新的Chart实例;
    chartRef.current = new Chart(ctx, {
      type: "line",
      data: chartData,
      options: {
        scales: {
          y: {
            beginAtZero: true,
          },
        },
      },
    });

    // 清理函数，在组件卸载时销毁图表
    return () => {
      if (chartRef.current) {
        chartRef.current.destroy();
      }
    };
  }, [chartData]);

  useEffect(() => {
    if (userChartRef.current) {
      userChartRef.current.destroy();
    }

    const userCtx = userChartContainer.current?.getContext("2d");

    if (!userChartContainer.current || !userCtx) return;

    // 创建新的Chart实例
    userChartRef.current = new Chart(userCtx, {
      type: "line",
      data: {
        labels: chartData.labels,
        datasets: userValues[selectedUser]
          ? [
              {
                label: `User ${selectedUser} Value`,
                data: userValues[selectedUser],
                borderColor: "red",
                fill: false,
              },
              {
                label: `Perturbed User ${selectedUser} Value`,
                data: perturbedUserValues[selectedUser],
                borderColor: "blue",
                fill: false,
              },
            ]
          : [],
      },
      options: {
        scales: {
          y: {
            beginAtZero: true,
          },
        },
      },
    });

    // 清理函数，在组件卸载时销毁图表
    return () => {
      if (userChartRef.current) {
        userChartRef.current.destroy();
      }
    };
  }, [selectedUser, chartData, userValues, perturbedUserValues]);

  return (
    <div>
      <mid>
        <h1>Local Differential Privacy</h1>

        <label htmlFor="userCount">Number of Users:</label>
        <div class="center">
          <input
            type="number"
            id="userCount"
            value={userCount}
            onChange={(e) => setUserCount(Number(e.target.value))}
          />
        </div>

        <label htmlFor="lowerBound">Data Lower Bound:</label>
        <div class="center">
          <input type="number" id="lowerBound" step="0.01" defaultValue="0" />
        </div>

        <label htmlFor="upperBound">Data Upper Bound:</label>
        <div class="center">
          <input type="number" id="upperBound" step="0.01" defaultValue="100" />
        </div>

        <label htmlFor="ldpParam">LDP Algorithm Parameter:</label>
        <div class="center">
          <input type="number" id="ldpParam" step="0.01" defaultValue="0.5" />
        </div>
        <br />
        <div class="center">
          <button onClick={startDataGeneration}>Start Data Generation</button>
        </div>
        <div class="center">
          <button onClick={stopDataGeneration}>Stop Data Generation</button>
        </div>
      </mid>
      <canvas
        ref={chartContainer}
        id="chart-container"
        width="800"
        height="400"
      ></canvas>

      <div>
        <mid>
          <label htmlFor="selectUser">Select User:</label>
        </mid>

        <div class="select">
          <select
            id="selectUser"
            value={selectedUser}
            onChange={(e) => setSelectedUser(Number(e.target.value))}
          >
            {[...Array(userCount)].map((_, index) => (
              <option key={index + 1} value={index + 1}>
                User {index + 1}
              </option>
            ))}
          </select>
        </div>
      </div>

      <div>
        <canvas
          ref={userChartContainer}
          id="user-chart-container"
          width="800"
          height="400"
        ></canvas>
      </div>
    </div>
  );
};

export default App;
